package com.sudo.boot.service.sys.jobservice.runnable;

import com.sudo.boot.base.constant.SysConstant;
import com.sudo.boot.base.exception.BizException;
import com.sudo.boot.base.util.ThreadLocalUtil;
import com.sudo.boot.common.constant.enums.ExceptionLimit;
import com.sudo.boot.common.constant.enums.RunModeType;
import com.sudo.boot.common.constant.enums.ThrowOrReturn;
import com.sudo.boot.common.util.task.TaskUtil;
import com.sudo.boot.mapper.sys.entity.SysLocalJob;
import com.sudo.boot.service.sys.SysLocalJobService;
import com.sudo.boot.service.sys.jobservice.tldata.ThreadLocalObject;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * @Author：DayDayUp
 * @Create：2023/4/18 17:06
 */
@Component
public class NextJobUtil {

    private static SysLocalJobService sysLocalJobService;
    private static AsyncTaskExecutor asyncTaskExecutor;

    public NextJobUtil(SysLocalJobService sysLocalJobService,
                       SchedulingTaskExecutor schedulingTaskExecutor){
        NextJobUtil.sysLocalJobService = sysLocalJobService;
        NextJobUtil.asyncTaskExecutor = schedulingTaskExecutor;
    }

    /**
     * 执行currentJobId下的子任务
     * @param currentJobId 当前任务ID
     * @param throwOrReturn 父任务异常或正常
     */
    public static void runNextLocalJobs(int currentJobId, ThrowOrReturn throwOrReturn) {
        SysLocalJob sysLocalJob = sysLocalJobService.querySysLocalJobById(currentJobId);
        if (!StringUtils.hasText(sysLocalJob.getNextJobIds())) {
            return;
        }
        if (throwOrReturn.getCode().equals(ThrowOrReturn.THROW.getCode())) {
            if (ExceptionLimit.EX_STOP.getCode().equals(sysLocalJob.getNextJobLimit())) {
                return;
            }
        }
        String[] jobIdArr = sysLocalJob.getNextJobIds().split(",");

        for (String jobIdStr : jobIdArr) {
            if (!StringUtils.hasText(jobIdStr)) {
                continue;
            }
            int jobId = Integer.parseInt(jobIdStr.trim());
            if (RunModeType.SYNC.getCode().equals(sysLocalJob.getNextJobMode())) {
                SysLocalJob syncLocalJob = sysLocalJobService.querySysLocalJobById(jobId);
                try {
                    if (syncLocalJob != null) {
                        Map<String, Object> jobConfigMap = ThreadLocalObject.initJobConfigMap(syncLocalJob);
                        ThreadLocalUtil.setTlMap(jobConfigMap);
                        TaskUtil.callTaskMethod(syncLocalJob.getBeanName(),syncLocalJob.getMethodName(),syncLocalJob.getMethodParams());
                    }
                } catch (Exception e) {
                    throw new BizException("子线程运行异常，子任务："+syncLocalJob.getId());
                }
            } else if (RunModeType.ASYNC.getCode().equals(sysLocalJob.getNextJobMode())) {
                String traceId = MDC.get(SysConstant.TRACE_ID);
                asyncTaskExecutor.execute(()->{
                    MDC.put(SysConstant.PARENT_TRACE_ID, traceId);
                    MDC.put(SysConstant.TRACE_ID,traceId+"."+jobIdStr);
                    SysLocalJob asyncLocalJob = sysLocalJobService.querySysLocalJobById(jobId);
                    try {
                        if (asyncLocalJob != null){
                            Map<String, Object> jobConfigMap = ThreadLocalObject.initJobConfigMap(asyncLocalJob);
                            ThreadLocalUtil.setTlMap(jobConfigMap);
                            TaskUtil.callTaskMethod(asyncLocalJob.getBeanName(),asyncLocalJob.getMethodName(),asyncLocalJob.getMethodParams());
                        }
                    } catch (Exception e) {
                        throw new BizException("子线程运行异常，子任务："+asyncLocalJob.getId());
                    }
                });
            }

        }
    }

}
